#切片
L = []
n = 1
while n <= 99:
    L.append(n)
    n = n + 2
print(L)

#切片
L = ['aa','bb','cc','dd','ee']
print(L[0:3])
print(L[:3])
print(L[-2:])
print(L[-2:-1])

S = list(range(100))
print(S)
print(S[:10])
print(S[-10:])
print(S[10:20])
print(S[:10:2])
print(S[::5])
print(S[:])
#元组切片仍是元组
s1 = (1,2,3,4,5,6,7)
print(s1[:3])
#字符串也可以切片
s2 = 'ABCDEFGH'
print(s2[:4])

#迭代(用for循环来遍历list或者tuple叫迭代)
d = {'a':1,'b':2,'c':3}
for key in d:
    print(key)

for value in d.values():
    print(value)

#判断一个对象是否是可迭代对象
from collections.abc import Iterable
print(isinstance('abc',Iterable))

for i,v in d.items():
    print(i,v)

#enumerate可以把一个list变成索引-元素对
for k,v in enumerate(['A','B','C']):
    print(k,v)

#列表生成式
list(range(1,11))
#生成x*x的列表
[x * x for x in range(1,11)]
#for循环后面还可以加上if判断，可以筛选出仅偶数的平方
[x * x for x in range(1,11) if x % 2 == 0]

[m + n for m in 'ABC' for n in 'XYZ']

#列出当前目录下的所有文件和目录名
import os
[d for d in os.listdir('.')]

d = {'x':'A','y':'B','z':'C'}
for k , v in d.items():
    print(k,'=',v)

[k + '=' + v for k, v in d.items()]

L = ['Hello','World','IBM','Apple']
[s.lower() for s in L]

[x for x in range(1, 11) if x % 2 == 0]
#if 在后边是筛选 error   [x for x in range(1, 11) if x % 2 == 0 else 0]

[x if x % 2 == 0 else -x for x in range(1, 11)]
#if 在前边是表达式 error   [x if x % 2 == 0 for x in range(1, 11)]

#生成器
#一边循环一边计算的机制
#1
g = (x * x for x in range(10))
#打印g
next(g)

for n in g:
    print(n)

def fib_1(max):
    n,a,b = 0,0,1
    while n < max:
        print(b)
        a,b = b,a + b
        n = n + 1
    return 'done'

#一个函数中包含了yield，那这个函数就不再是一个普通的函数，是一个generator，调用这个函数将返回一个generator
def fib_2(max):
    n,a,b = 0,0,1
    while n < max:
        yield b
        a,b = b,a + b
        n = n + 1
    return 'done'

#yield 执行顺序是每次调用next时执行，遇到yield语句返回，再次执行时从上次返回的yield语句处执行
def odd():
    print('step 1')
    yield 1
    print('step 2')
    yield 3
    print('step 3')
    yield 5
o = odd()
next(o)
next(o)
next(o)
#调用generator函数会创建一个generator对象，多次调用generator函数会创建多个相互独立的generator。
#若是一直调用next(odd())则每次都返回1
#正确用法
g = odd()
next(g)
next(g)
next(g)

#用for循环调用generator时，拿不到return语句的返回值，如果要拿到返回值，必须捕获StopIteration错误
g = fib_2(6)
while True:
    try:
        x = next(g)
        print('g:', x)
    except StopIteration as e:
        print('Generator return value:', e.value)
        break

#练习，杨辉三角，把每一行看做一个list，试写一个generator，不断输出下一行的list
'''
          1
         / \
        1   1
       / \ / \
      1   2   1
     / \ / \ / \
    1   3   3   1
   / \ / \ / \ / \
  1   4   6   4   1
 / \ / \ / \ / \ / \
1   5   10  10  5   1
'''
def triangles():
    L = [1]
    while True:
        yield L
        L = [1] + [L[i] + L[i+1] for i in range(len(L) - 1)] + [1]
n = 0
for t in triangles():
    print(t)
    n = n + 1
    if n == 10:
        break

#迭代器
#我们已经知道，可以直接作用于for循环的数据类型有以下几种：

#一类是集合数据类型，如list、tuple、dict、set、str等；

#一类是generator，包括生成器和带yield的generator function。

#这些可以直接作用于for循环的对象统称为可迭代对象：Iterable。

#可以使用isinstance()判断一个对象是否是Iterable对象

from collections.abc import Iterable

isinstance('asdff',Iterable)

#可以被next()函数调用并不断返回下一个值的对象称为迭代器：Iterator。

#可以使用isinstance()判断一个对象是否是Iterator对象

from collections.abc import Iterator

isinstance('abdhf',Iterator)

#生成器都是Iterator对象，但list、dict、str虽然是Iterable，却不是Iterator。

#把list、dict、str等Iterable变成Iterator可以使用iter()函数：

isinstance(iter('sasdd'),Iterator)

#Python的for循环本质上就是通过不断调用next()函数实现的，例如：
for x in [1, 2, 3, 4, 5]:
    pass

# 首先获得Iterator对象:
it = iter([1, 2, 3, 4, 5])
# 循环:
while True:
    try:
        # 获得下一个值:
        x = next(it)
    except StopIteration:
        # 遇到StopIteration就退出循环
        break




